package com.example.kotlin

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue

/**
 * 使用 remember 存储对象的可组合项包含内部状态，这会使该可组合项有状态。在调用方不需要控制状态，并且不必自行管理状态便可使用状态的情况下，
 * “有状态”会非常有用。但是，具有内部状态的可组合项往往不易重复使用，也更难测试。
 *
 * 不保存任何状态的可组合项称为无状态可组合项。如需创建无状态可组合项，一种简单的方法是使用状态提升。
 *
 * Compose 中的状态提升是一种将状态移至可组合项的调用方以使可组合项无状态的模式。Jetpack Compose 中的常规状态提升模式是将状态变量替换为两个参数：
 * value: T：要显示的当前值
 * onValueChange: (T) -> Unit：请求更改值的事件，其中 T 是建议的新值
 *以这种方式提升的状态具有一些重要的属性：
 *单一可信来源：通过移动状态，而不是复制状态，我们可确保只有一个可信来源。这有助于避免 bug。
 *封装：只有有状态可组合项能够修改其状态。完全是在内部操作。
 *可共享：可与多个可组合项共享提升的状态。如果您想在另一个可组合项中读取 name，可以通过变量提升来做到这一点。
 *可拦截：无状态可组合项的调用方可以在更改状态之前决定忽略或修改事件。
 *解耦：无状态 ExpandingCard 的状态可以存储在任何位置。例如，现在可以将 name 移入 ViewModel。
 *
 * 状态下降、事件上升的这种模式称为单向数据流 (UDF)，而状态提升就是我们在 Compose 中实现此架构的方式。如需了解相关详情，请参阅 Compose 架构文档。https://developer.android.google.cn/jetpack/compose/architecture?hl=zh-cn#udf-compose
 *
 * 要点：提升状态时，有三条规则可帮助您弄清楚状态应去向何处：
 *
 *状态应至少提升到使用该状态（读取）的所有可组合项的最低共同父项。
 *状态应至少提升到它可以发生变化（写入）的最高级别。
 *如果两种状态发生变化以响应相同的事件，它们应提升到同一级别。
 *您可以将状态提升到高于这些规则要求的级别，但如果未将状态提升到足够高的级别，则遵循单向数据流会变得困难或不可能。
 * */

///////////////////////////////////////////////////////////////////////////
// Before
///////////////////////////////////////////////////////////////////////////
@Composable
fun WaterCounter(modifier: Modifier = Modifier) {
    Column(modifier = modifier.padding(16.dp)) {
        var count by remember { mutableStateOf(0) }
        if (count > 0) {
            Text("You've had $count glasses.")
        }
        Button(onClick = { count++ }, Modifier.padding(top = 8.dp), enabled = count < 10) {
            Text("Add one")
        }
    }
}

///////////////////////////////////////////////////////////////////////////
// 状态提升之后
///////////////////////////////////////////////////////////////////////////
@Composable
private fun StatefulCounter(modifier: Modifier = Modifier) {
    var count by rememberSaveable { mutableStateOf(0) }
    StatelessCounter(count, { count++ }, modifier)
}


@Composable
private fun StatelessCounter(count: Int, onIncrement: () -> Unit, modifier: Modifier = Modifier) {
    Column(modifier = modifier.padding(16.dp)) {
        if (count > 0) {
            Text("You've had $count glasses.")
        }
        Button(onClick = onIncrement, Modifier.padding(top = 8.dp), enabled = count < 10) {
            Text("Add one")
        }
    }
}

//正确的列表写法
class WellnessTask(
    val id: Int,
    val label: String,
    val checked: MutableState<Boolean> = mutableStateOf(false)
)//添加了checked并将选中状态和逻辑迁移到 ViewModel


//或使用委托写法
class WellnessTask2(
    val id: Int,
    val label: String,
    initialChecked: Boolean = false
) {
    var checked by mutableStateOf(initialChecked)
}

private val taskList = mutableListOf<WellnessTask>()

@Composable
private fun WellnessScreen(modifier: Modifier = Modifier) {
    Column(modifier = modifier) {
        StatefulCounter()

        val list = remember { taskList.toMutableStateList() }
        WellnessTasksList(list = list, onCloseTask = { task -> list.remove(task) })
    }
}

@Composable
private fun WellnessTasksList(
    list: List<WellnessTask>,
    onCloseTask: (WellnessTask) -> Unit,
    modifier: Modifier = Modifier
) {
    LazyColumn(modifier = modifier) {
        items(
            items = list,
            key = { task -> task.id }
        ) { task ->
            WellnessTaskItem(taskName = task.label, onClose = { onCloseTask(task) })
        }
    }
}

@Composable
private fun WellnessTaskItem(
    taskName: String, onClose: () -> Unit, modifier: Modifier = Modifier
) {
    var checkedState by rememberSaveable { mutableStateOf(false) }

    WellnessTaskItem(
        taskName = taskName,
        checked = checkedState,
        onCheckedChange = { newValue -> checkedState = newValue },
        onClose = onClose,
        modifier = modifier,
    )
}

@Composable
fun WellnessTaskItem(
    taskName: String,
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    onClose: () -> Unit,
    modifier: Modifier = Modifier
) {
    Row(
        modifier = modifier, verticalAlignment = Alignment.CenterVertically
    ) {
        Text(
            modifier = Modifier
                .weight(1f)
                .padding(start = 16.dp),
            text = taskName
        )
        Checkbox(
            checked = checked,
            onCheckedChange = onCheckedChange
        )
        IconButton(onClick = onClose) {
            Icon(Icons.Filled.Close, contentDescription = "Close")
        }
    }
}